package org.surelink.radius.server;


import org.surelink.radius.cache.ClientCache;
import org.surelink.radius.cache.UserCache;
import org.surelink.radius.middleware.AuthMiddleware;
import org.surelink.radius.model.Client;
import org.surelink.radius.model.User;
import org.surelink.radius.utils.AuthLogger;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.tinyradius.packet.AccessRequest;
import org.tinyradius.packet.RadiusPacket;
import org.tinyradius.util.RadiusException;
import org.tinyradius.util.RadiusServer;
import org.tinyradius.util.RadiusStat;

import javax.annotation.PostConstruct;
import java.net.InetSocketAddress;
import java.util.List;

public class AuthServer extends RadiusServer{
    private static final Logger log = Logger.getLogger(AuthServer.class);

    List<AuthMiddleware> middlewares;

    private int port;

    @Autowired
    private UserCache userCache;

    @Autowired
    private ClientCache clientCache;

    @Autowired
    private AuthLogger radiuslog;

    @Autowired
    private RadiusStat stat;

    public List<AuthMiddleware> getMiddlewares() {
        return middlewares;
    }

    public void setMiddlewares(List<AuthMiddleware> middlewares) {
        this.middlewares = middlewares;
    }


    public  AuthServer(int port){
        this.port = port;
    }

    @PostConstruct
    public void startServer(){
        setAuthPort(port);
        setRadiusStat(stat);
        start(true,false);
        log.info("RADIUS认证服务器监听端口["+port+"]成功");
    }

    public String getSharedSecret(InetSocketAddress client) {
        Client cl = clientCache.get(client.getAddress().getHostAddress());
        if(cl==null)
            return null;
        return cl.getSecret();
	}

	public String getUserPassword(String userName) {
		return userCache.get(userName).getPassword();
	}

	public void afterExecute(RadiusPacket request, InetSocketAddress client) {
		
	}
	
	/**
	 * 认证请求处理
	 */
	public RadiusPacket accessRequestReceived(AccessRequest request,
			InetSocketAddress client) throws RadiusException {


        radiuslog.logRequest(request);

		RadiusPacket response = new RadiusPacket(RadiusPacket.ACCESS_ACCEPT, request.getPacketIdentifier());
		copyProxyState(request, response);

        User user = userCache.get(request.getUserName());

        for( AuthMiddleware middleware:middlewares )
        {
             try{
                 middleware.onAuth(user,request,response);
                 if(response.getPacketType() == RadiusPacket.ACCESS_REJECT)
                     break;

             }catch(Exception e){
                 String err = String.format("AuthServer:accessRequestReceived error:" +
                         "userName=%s;middleware=%s",
                         request.getAttribute("User-Name"),
                         middleware.getClass().toString());
                  log.error(err,e);
             }
        }
        radiuslog.logResponse(request,response);
		return response;
	}






}
